一、约束
	主键约束：primary key。
		1. 注意：
			1. 含义：非空且唯一    //第三个特点  可以被引用（外键学习）
			2. 一张表只能有一个字段为主键
			3. 主键就是表中记录的   唯一   标识//联合主键也是一个主键,联合主键创建方式,在创建表时添加primary key(列名1,列名2),

		2. 在创建表时，添加主键约束  //掌握
			create table stu(
				id int primary key,-- 给id添加主键约束
				name varchar(20)
			);

		3. 删除主键
			-- 错误 alter table stu modify id int ;
			ALTER TABLE stu DROP PRIMARY KEY;

		4. 创建完表后，添加主键
			ALTER TABLE stu MODIFY id INT PRIMARY KEY;
		
		5. 自动增长：
			1.  概念：如果某一列是数值类型的，使用 auto_increment 可以来完成值得自动增长
				//使用前提：这一列必须是数值类型
				//使用场景：一般和主键一起使用

			2. 在创建表时，添加主键约束，并且完成主键自增长
			create table stu(
				id int primary key auto_increment,-- 给id添加主键约束
				name varchar(20)
			);
			3. 删除自动增长
			ALTER TABLE stu MODIFY id INT;
			//如果id是主键,这样并不会对主键有任何影响,主键仍然存在
			4. 添加自动增长
			ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
			//如果id是主键,这样并不会对主键有任何影响,主键仍然存在
			
		//自动增长的弊端？
			//对于集群环境自增长是没有效果的	使用UUID
				  UUID uuid = UUID.randomUUID();
					System.out.println(uuid);
					System.out.println(uuid.toString().replace("-",""));
					System.out.println(uuid.toString().length());
					//267cb5fc85f64a568a12a4d2bfe90cee
					
					
	 外键约束：foreign key,让表于表产生关系，从而保证数据的正确性。
		//为什么要使用外键？
			让表于表产生关系
		//使用外键有什么好处？
			保证数据的正确性
	 
		1. 在创建表时，可以添加外键
			* 语法：
				create table 表名(
					....
					外键列
					constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称)
					//外键的名称不做限制，名字的用处是用来在删除时使用
				);

		2. 删除外键
			ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;

		3. 创建表之后，添加外键
			ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);					
			//外键名称可以是任意名称,只是为了方便删除时使用,当把主键设为外键时,外键名称也可以和主键名称相同
			//外键可以为任意列,可以为主键,也可以自己新建一个列设为外键
			//与外键关联的主表列的字段内容除了必须包含外键列字段的所有内容,也可以有自己的内容,但是二者的数据类型必须相同,数据类型的长度可以不同,只要保证内容相同即可
			//外键对应的的另一张表中的列必须是唯一的,通常为主键
			//外键列的数据字段可以为null,如果外键列中有null,主表列中也有null,那么在多表查询时,查询a.name=b.id,null对应的行的数据不会被查询出来
			
		4.图形化界面工具添加外键,改变表->外部键->约束名(外键名称)->引用列(外键列的列名)->引用数据库(数据库名)->引用表(主表名)->引用列(主表的被引用的列名)->更新和删除选项可以自己选择是否级联更新和级联删除(如果之前有了级联更新或者级联删除可以选择NO Action,让其不再有级联更新和删除的功能)
		
	5. 级联操作  //了解
		//级联相关的操作一定要慎用，一般在公司中都是由数据库管理员去做（DBA）
		1. 添加级联操作
			语法：ALTER TABLE 表名 ADD CONSTRAINT 外键名称 
					FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE  ;
					//只能用这样的方法去进行操作
		2. 分类：
			1. 级联更新：ON UPDATE CASCADE 
			//级联更新指的是如果更改主表中被引用列的数据,从表中的外键列数据会跟随主表改变
			
			2. 级联删除：ON DELETE CASCADE 		
			//级联删除指的是如果要删除主表中的数据,从表中的外键列数据会跟随主表被删除
			//级联更新和级联删除都是从表依据主表的改变而进行改变的
数据库的设计			
		1. 分类：
			1. 一对一(了解)：
				* 如：人和身份证
				* 分析：一个人只有一个身份证，一个身份证只能对应一个人
			2. 一对多(多对一)：
				* 如：部门和员工
				* 分析：一个部门有多个员工，一个员工只能对应一个部门
			3. 多对多：
				* 如：学生和课程
				* 分析：一个学生可以选择很多门课程，一个课程也可以被很多学生选择
		//不同的场景下，表和表之间的关系是会变得
			//学生和老师  在不同情况下可能是多对一  也可能是多对多
			
		2. 实现关系：
			1. 一对多(多对一)：
				* 如：部门和员工
				//* 实现方式：在多的一方建立外键，指向一的一方的主键。//掌握（☆☆☆☆☆）(可以为空,但是必须唯一)
					//不一定是主键，只要该字段是唯一的就可以。  一般情况下我们使用的都是主键
					//第一：你必须分清楚  谁是一 谁是多
			2. 多对多：
				* 如：学生和课程
				* 实现方式：多对多关系实现需要借助第三张中间表。中间表至少包含两个字段，这两个字段作为第三张表的外键，分别指向两张表的主键
				//学生和课程之间为什么是多对多关系？
					因为一个学可以选择多个课程
					一个课程可以被多个学生选择
				//多对多关系在mysql中是怎么实现的？
					在mysql中其实是没有多对多关系的，只有一对多。多对多其实是通过第三张表模拟出来的。
				
				//小总结：以后我们怎么设计多对多关系
					第一步：你得分析出两张表是多对多关系
					第二步：创建一个中间表
					第三步：中间表至少包含两个字段
					第四步：在中间 表和A和B表之间建立多对一的关系 （其中中间表是多，A和B表是一）
					第五步：建立外键关系，在多的一方建立外键指向一的一方的主键
			
			
			3. 一对一//(了解)：
				* 如：人和身份证
				* 实现方式：一对一关系实现，可以在任意一方添加唯一外键指向另一方的主键。	
					//就是在从表的主键既是主键也是外键
					//外键可以为空,但是必须唯一,主表被引用的列也可以为空,但是必须唯一
			
	2. 数据库设计的范式
	* 概念：设计数据库时，需要遵循的一些规范。要遵循后边的范式要求，必须先遵循前边的所有范式要求

		设计关系数据库时，遵从不同的规范要求，设计出合理的关系型数据库，这些不同的规范要求被称为不同的范式，各种范式呈递次规范，越高的范式数据库冗余越小。
		目前关系数据库有六种范式：第一范式（1NF）、第二范式（2NF）、第三范式（3NF）、巴斯-科德范式（BCNF）、第四范式(4NF）和第五范式（5NF，又称完美范式）。

	* 分类：
		1. 第一范式（1NF）：每一列都是不可分割的原子数据项
		2. 第二范式（2NF）：在1NF的基础上，非码属性必须完全依赖于码（在1NF基础上消除非主属性对主码的部分函数依赖）
			* 几个概念：
				1. 函数依赖：A-->B,如果通过A属性(属性组)的值，可以确定唯一B属性的值。则称B依赖于A
					例如：学号-->姓名。  （学号，课程名称） --> 分数
				2. 完全函数依赖：A-->B， 如果A是一个属性组，则B属性值得确定需要依赖于A属性组中所有的属性值。
					例如：（学号，课程名称） --> 分数
				3. 部分函数依赖：A-->B， 如果A是一个属性组，则B属性值得确定只需要依赖于A属性组中某一些值即可。
					例如：（学号，课程名称） -- > 姓名
				4. 传递函数依赖：A-->B, B -- >C . 如果通过A属性(属性组)的值，可以确定唯一B属性的值，在通过B属性（属性组）的值可以确定唯一C属性的值，则称 C 传递函数依赖于A
					例如：学号-->系名，系名-->系主任
				5. 码：如果在一张表中，一个属性或属性组，被其他所有属性所完全依赖，则称这个属性(属性组)为该表的码
					例如：该表中码为：（学号，课程名称）
					* 主属性：码属性组中的所有属性
					* 非主属性：除过码属性组的属性
					
		3. 第三范式（3NF）：在2NF基础上，任何非主属性不依赖于其它非主属性（在2NF基础上消除传递依赖）		
			
			举例：
				id 姓名 性别  联系方式
				1  张三 男	email:zs@126.com,phone:88886666
				2  李四 女	email:ls@126.com,phone:66668888

			依据第一范式修改后：
				id 姓名 性别  邮箱				手机号
				1  张三 男	email:zs@126.com	phone:88886666
				2  李四 女	email:ls@126.com	phone:66668888
			
		//  第一范式：每一列不可再分
		//  第二范式：消除部分依赖
		//  第三范式：消除传递依赖	
	
	//三大范式的弊端		
		表太多，查询起来效率变低
		一般而言，在设计表的时候只要能遵循到第二范式就差不多了
			
数据库的备份和还原
	1. 命令行：
	* 语法：
		* 备份： mysqldump -u用户名 -p密码 数据库名称 > 保存的路径
			//(1)末尾没有分号、不需要登陆mysql、直接在黑窗口操作。
			//（2）备份出来的sql脚本中不包含创建数据库的语句。（还原的时候，你必须自己先创建一个数据库,数据库的名字可以随便命名）
		* 还原：
			1. 登录数据库
			2. 创建数据库(数据库的名字可以随便命名)
			3. 使用数据库
			4. 执行文件。source 文件路径
		*还原方式二：
			mysql -uroot -proot java28 < D:/a.sql(此命令行在黑窗口直接输入,Java28是新创建的数据库名,将来要将D盘下的备份文件导入到该数据库中)
	2. 图形化工具：
	//这种方式不需要重新建立数据库,因为在备份文件中已经包含了创建数据库的命令行,且创建的数据库的名称和之前备份的数据库的名称一样
			
//---------------------------------------------------------------------------------------------------------------------

day03Mysql多表和事务

今日内容	
	1. 多表查询//特别重要

	2. 事务//重要

	3. DCL//了解
			
	* 查询语法：
	select
		列名列表
	from
		表名列表
	where....
	* 准备sql
		# 创建部门表
		CREATE TABLE dept(
			id INT PRIMARY KEY AUTO_INCREMENT,
			NAME VARCHAR(20)
		);
		INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');
		# 创建员工表
		CREATE TABLE emp (
			id INT PRIMARY KEY AUTO_INCREMENT,
			NAME VARCHAR(10),
			gender CHAR(1), -- 性别
			salary DOUBLE, -- 工资
			join_date DATE, -- 入职日期
			dept_id INT,
			FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键，关联部门表(部门表的主键)
		);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
		INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);
	* 笛卡尔积：
		* 有两个集合A,B .取这两个集合的所有组成情况。
		* 要完成多表查询，需要消除无用的数据
		
		例如：
			{a,b,c}    {1,2}
			{a1,a2,b1,b2,c1,c2}
			
	问题：
		1.为什么要用笛卡尔积？
			就是为了把两张表中的数据进行组合
		2.弊端
			产生了大量的冗余（无用）数据
		3.怎么解决
			去除笛卡尔积（通过where条件来去除）
			
		4.总结：只要使用连接查询的时候，必须要去除笛卡尔积
		
		
	* 多表查询的分类：
		1. 内连接查询：
			1. 隐式内连接：使用where条件消除无用数据
				* 例子：
				-- 查询所有员工信息和对应的部门信息

				SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
				
				-- 查询员工表的名称，性别。部门表的名称
				SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
				
				SELECT 
					t1.name, -- 员工表的姓名
					t1.gender,-- 员工表的性别
					t2.name -- 部门表的名称
				FROM
					emp t1,
					dept t2
				WHERE 
					t1.`dept_id` = t2.`id`;		
			
			
			
			
			
			